package cz.muni.fi.pv112.cranesimulator.models.scene;

import com.jogamp.opengl.util.texture.Texture;
import cz.muni.fi.pv112.cranesimulator.models.Model;
import java.io.IOException;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import static cz.muni.fi.pv112.cranesimulator.utils.handlers.opengl.DisplayListHandler.storeModelToDisplayList;
import static cz.muni.fi.pv112.cranesimulator.utils.handlers.opengl.TextureHandler.loadTextures;

/**
 * Class representing a skybox composed of 6 quads with textures
 *
 * @author Michal Ďuriš
 */
public class Skybox extends Model {

    private Texture[] textures;

    public final static float EDGE_LENGTH = 400.0f;
    public final static float HALF_EDGE_LENGTH = 350.0f;

    private final static String[] texturePaths = {
        "/cz/muni/fi/pv112/cranesimulator/resources/textures/models/skybox/TropicalSunnyDayBack2048.png",
        "/cz/muni/fi/pv112/cranesimulator/resources/textures/models/skybox/TropicalSunnyDayFront2048.png",
        "/cz/muni/fi/pv112/cranesimulator/resources/textures/models/skybox/TropicalSunnyDayRight2048.png",
        "/cz/muni/fi/pv112/cranesimulator/resources/textures/models/skybox/TropicalSunnyDayLeft2048.png",
        "/cz/muni/fi/pv112/cranesimulator/resources/textures/models/skybox/TropicalSunnyDayUp2048.png"
    /*
     * "/cz/muni/fi/pv112/cranesimulator/resources/textures/models/skybox/TropicalSunnyDayDown2048.png"
     */
    };

    private final static float[][] vertexCoords = {
        /*
         * Front side - texture back
         */
        {-HALF_EDGE_LENGTH, EDGE_LENGTH, HALF_EDGE_LENGTH},
        {HALF_EDGE_LENGTH, EDGE_LENGTH, HALF_EDGE_LENGTH},
        {HALF_EDGE_LENGTH, 0.0f, HALF_EDGE_LENGTH},
        {-HALF_EDGE_LENGTH, 0.0f, HALF_EDGE_LENGTH},
        /*
         * Back side - texture front
         */
        {HALF_EDGE_LENGTH, 0.0f, -HALF_EDGE_LENGTH},
        {-HALF_EDGE_LENGTH, 0.0f, -HALF_EDGE_LENGTH},
        {-HALF_EDGE_LENGTH, EDGE_LENGTH, -HALF_EDGE_LENGTH},
        {HALF_EDGE_LENGTH, EDGE_LENGTH, -HALF_EDGE_LENGTH},
        /*
         * Right side
         */
        {HALF_EDGE_LENGTH, EDGE_LENGTH, HALF_EDGE_LENGTH},
        {HALF_EDGE_LENGTH, EDGE_LENGTH, -HALF_EDGE_LENGTH},
        {HALF_EDGE_LENGTH, 0.0f, -HALF_EDGE_LENGTH},
        {HALF_EDGE_LENGTH, 0.0f, HALF_EDGE_LENGTH},
        /*
         * Left side
         */
        {-HALF_EDGE_LENGTH, EDGE_LENGTH, HALF_EDGE_LENGTH},
        {-HALF_EDGE_LENGTH, EDGE_LENGTH, -HALF_EDGE_LENGTH},
        {-HALF_EDGE_LENGTH, 0.0f, -HALF_EDGE_LENGTH},
        {-HALF_EDGE_LENGTH, 0.0f, HALF_EDGE_LENGTH},
        /*
         * Top side
         */
        {HALF_EDGE_LENGTH, EDGE_LENGTH, HALF_EDGE_LENGTH},
        {HALF_EDGE_LENGTH, EDGE_LENGTH, -HALF_EDGE_LENGTH},
        {-HALF_EDGE_LENGTH, EDGE_LENGTH, -HALF_EDGE_LENGTH},
        {-HALF_EDGE_LENGTH, EDGE_LENGTH, HALF_EDGE_LENGTH}, /*
     * Bottom side
     * {HALF_EDGE_LENGTH, 0.0f, HALF_EDGE_LENGTH},
     * {-HALF_EDGE_LENGTH, 0.0f, HALF_EDGE_LENGTH},
     * {-HALF_EDGE_LENGTH, 0.0f, -HALF_EDGE_LENGTH},
     * {HALF_EDGE_LENGTH, 0.0f, -HALF_EDGE_LENGTH}
     */};

    private final static float[][] textureCoords = {
        /*
         * Front side
         */
        {0, 1},
        {1, 1},
        {1, 0},
        {0, 0},
        /*
         * Back side
         */
        {0, 0},
        {1, 0},
        {1, 1},
        {0, 1},
        /*
         * Right side
         */
        {0, 1},
        {1, 1},
        {1, 0},
        {0, 0},
        /*
         * Left side
         */
        {1, 1},
        {0, 1},
        {0, 0},
        {1, 0},
        /*
         * Top side
         */
        {0, 1},
        {0, 0},
        {1, 0},
        {1, 1}, /*
     * Bottom side
     * {0, 0},
     * {1, 0},
     * {1, 1},
     * {0, 1}
     */};

    private final static float[][] normalCoords = {
        /*
         * Front side
         */
        {0, 0, -1},
        {0, 0, -1},
        {0, 0, -1},
        {0, 0, -1},
        /*
         * Back side
         */
        {0, 0, 1},
        {0, 0, 1},
        {0, 0, 1},
        {0, 0, 1},
        /*
         * Right side
         */
        {-1, 0, 0},
        {-1, 0, 0},
        {-1, 0, 0},
        {-1, 0, 0},
        /*
         * Left side
         */
        {1, 0, 0},
        {1, 0, 0},
        {1, 0, 0},
        {1, 0, 0},
        /*
         * Top side
         */
        {0, -1, 0},
        {0, -1, 0},
        {0, -1, 0},
        {0, -1, 0}, /*
     * Bottom side
     * {0, 1, 0},
     * {0, 1, 0},
     * {0, 1, 0},
     * {0, 1, 0}
     */};

    public Skybox() {
    }

    public void init(GL gl) {
        try {
            textures = loadTextures(gl, texturePaths, true, null);

            displayListID = storeModelToDisplayList(gl.getGL2(), this, textures,
                    GL2.GL_CLAMP_TO_EDGE,
                    GL2.GL_CLAMP_TO_EDGE);
        } catch (IOException ex) {
            //@TODO: maybe throw some runtime error or something
            System.err.println("Error during loading textures !!!");
        }
    }

    @Override
    public float[][] getVertexCoords() {
        return vertexCoords;
    }

    @Override
    public float[][] getNormalCoords() {
        return normalCoords;
    }

    @Override
    public float[][] getTextureCoords() {
        return textureCoords;
    }

    public Texture[] getTextures() {
        return textures;
    }

}
